#/*************************************************************************
#    > File Name: Param_Operation.py
#    > Author: Yan Wang
#    > Mail: wangyan@imnu.edu.cn
#    > Created Time: 2022年10月27日 星期四 14时47分14秒
# ************************************************************************/
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Library import *
from Load_Lib import *

class Param_BASDA(object):
	BASDA_Dir={}
	BASDA_Control={}
	BASDA_Results={}
	BASDA_Setting={}

	_BASDA_path={}
	_BASDA_file={}

	_param_dir={}
	_process={}
	_ARCH_para={}

	def __init__(self, param_dir, process, ARCH_para):
		self._param_dir=param_dir.Dir()
		self._process  =process.Var()
		self._ARCH_para  =ARCH_para.Dir()
		self.Set_Para()

	def Set_Input(self, param_dir, process, ARCH_para):
		self._param_dir=param_dir.Dir()
		self._process  =process.Var()
		self._ARCH_para  =ARCH_para.Var()
		self.Set_Para(self._param_dir, self._process, self._ARCH_para)

# 设置最终输出结果
	def Set_Para(self):
		self.Param_BASDA_Dir    (self._param_dir, self._process)
		self.Param_BASDA_Control(self._param_dir, self._process, self._ARCH_para)


# 输出
	def Dir(self):
		return(self.BASDA_Dir)

	def Control(self):
		return(self.BASDA_Control)

	# 生成 BASDA 中的 Path 文件

	def Param_BASDA_Path(self, process_name,out_folder):
		param_path={"origin": {"process"     :"PROCESS                   : {}_$fnum".format(process_name),
								"out_folder" :"OUTPUT_FOLDER             : "+str(out_folder),
								"tmp"        :"RECORD_FILE               : \"tmp/{}_$fnum.dat\"".format(process_name),
								"in_folder"  :"INPUT_FOLDER              : './control/control_scan_{}'".format(process_name), #这里要和上面定义的BASDA_target_control_folder对应
								"file"       :"INPUT_FILE                : \"file_$fnum.dat\""},
					"source" : "path.dat",
					"labels" : {"PROCESS                   : 'process'":0,
								"OUTPUT_FOLDER             : 'events/Event_scan_1'":0,
								"RECORD_FILE               : 'tmp/tmp_h_w4b_1.dat'":0, 
								"INPUT_FOLDER              : './control/control_BASDA'":0,
								"INPUT_FILE                : 'file.dat'":0}
					}
		self._BASDA_path=param_path
		return(param_path)




	def Path_Print(self):
		print("			BASDA path is : ")
		print("				origin : ")
		for key in self._BASDA_path["origin"] :
			print("					"+str(key)+" : ", self._BASDA_path["origin"][key])
		print("				source : ", self._BASDA_path["source"])
		print("				labels : ")
		for key in self._BASDA_path["labels"] :
			print("					"+str(key)+" : ", self._BASDA_path["labels"][key])




	def Param_BASDA_File(self):
		param_file={"origin": {"file":"FILE_0            : xsection_$fnum.dat"},
						"source":"file.dat",
						"labels":{"FILE_0            : xsection_1.dat":0}
						}
		self._BASDA_file=param_file
		return(param_file)

	def File_Print(self):
		print("			BASDA file is : ")
		print("				origin : ")
		for key in self._BASDA_file["origin"] :
			print("					"+str(key)+" : ", self._BASDA_file["origin"][key])
		print("				source : ", self._BASDA_file["source"])
		print("				labels : ")
		for key in self._BASDA_file["labels"] :
			print("					"+str(key)+" : ", self._BASDA_file["labels"][key])




	def Param_BASDA_Xection(self, event_data_file):
		param_xection={"origin": {"file":"        "+str(event_data_file)+"        : $fvalue"},
						"source":"xsection.dat",
						"labels":{"        file  : 1.554":0}
						}
		self._BASDA_xection=param_xection
		return(param_xection)


	def Xection_Print(self):
		print("			BASDA xection is : ")
		print("				origin : ")
		for key in self._BASDA_xection["origin"] :
			print("					"+str(key)+" : ", self._BASDA_xection["origin"][key])
		print("				source : ", self._BASDA_file["source"])
		print("				labels : ")
		for key in self._BASDA_xection["labels"] :
			print("					"+str(key)+" : ", self._BASDA_xection["labels"][key])



	# 生成 BASDA 中的 Path 文件
	def Param_BASDA_Control(self, param_dir,process, para):
		self.BASDA_Control["dir"]={"source":param_dir["BASDA_template"],"target":self.BASDA_Dir["control_folder"]}
		self.Param_BASDA_Path(process["process_event_kind"],self.BASDA_Dir["event_general_folder"])
		self.Param_BASDA_File()
		self.Param_BASDA_Xection(para["output_event_file"])
		self.BASDA_Control["replaced_para"]={"path":self._BASDA_path, 
											"file":self._BASDA_file,
											"xection":self._BASDA_xection}
		return


	def Control_Print(self):
		print("	The BASDA Control is : ")
		print("		BASDA control dir : ")
		print("			source : ", self.BASDA_Control["dir"]["source"])
		print("			target : ", self.BASDA_Control["dir"]["target"])
		print("		BASDA replaced_para : ")
		self.Path_Print()
		self.File_Print()
		self.Xection_Print()


	def Replace_Para_in_BASDA(self, input_para, cut_cross):
		df_num=len(cut_cross)
		
		output_list={}
		for key in input_para:
			param_list_all=[]
			for cross_num, cross_data in enumerate(cut_cross):
				format_num=str(cross_num+1).rjust(2,"0")
				values={"fnum":format_num,"fvalue":str(cross_data)}
				input_dict=Trans_MultiValue_to_Dict(input_para[key],values)   #values传参到input_para[key]
				input_list=Trans_Dict_to_List(input_dict)   #将上述字典转化成列表
				param_list_all.append(input_list)   #在末尾添加input_list
			output_list[key]=param_list_all
		
		return(output_list)

# 生成 BASDA 的运行参数
	def Generate_Multi_Control_File(self, cut_cross):
		target_folder=Copy_File(self.BASDA_Control["dir"]["source"],self.BASDA_Control["dir"]["target"])   #复制文件
		
# generate param files
		
		input_origin={}
		input_replaced_para=self.BASDA_Control["replaced_para"]
		for key in input_replaced_para:
			input_origin[key] = input_replaced_para[key]["origin"]
		replaced_para=self.Replace_Para_in_BASDA(input_origin, cut_cross)   #
		for key in input_replaced_para:
			File_Replace_with_Para(replaced_para[key], input_replaced_para[key]["source"], target_folder, input_replaced_para[key]["labels"])
		
		return(replaced_para)



	def Param_BASDA_Dir(self, param_dir,process):
		self.BASDA_Dir["control_folder"]= param_dir["BASDA"] / "control/control_scan_{}".format(process["process_event_kind"])
		self.BASDA_Dir["parallel_output_folder"]=param_dir["output_folder"] / "parallel_tmp/BASDA_results_{fname}/".format(fname=process["process_event_kind"]) / "BASDA_{}"
		# 提取最终significance，利用BASDA的输出结果
		self.BASDA_Dir["event_general_folder"]= Path("events/Event_Analyse_scan_{fname}".format(fname=process["process_event_kind"])+"_$fnum")
		self.BASDA_Dir["event_general_folder_string"]= Path("events/Event_Analyse_scan_{fname}".format(fname=process["process_event_kind"])+"_{fnum}")
		self.BASDA_Dir["out_table_file"]= param_dir["BASDA"] / self.BASDA_Dir["event_general_folder_string"] / "data/125/output_table_combined_125.dat"

		self.BASDA_Dir["param_out_file"]=param_dir["output_folder"] / "param/{fname}_for_BASDA.dat".format(fname=process["process_event_kind"])


		self.BASDA_Dir["hotmap_dat_file"]=param_dir["output_folder"] / "hotmap_data/{fname}_for_BASDA_significance.dat".format(fname=process["process_event_kind"])
		self.BASDA_Dir["hotmap_C_file"]=param_dir["output_folder"] / "hotmap_code/{fname}_for_BASDA_significance.C".format(fname=process["process_event_kind"])
		
		self.BASDA_Setting["hotmap_variable_name"]="sig_data"
		self.BASDA_Setting["plot"]={"dat_file": self.BASDA_Dir["hotmap_dat_file"],
								"C_file": self.BASDA_Dir["hotmap_C_file"],
								"bins":process["plot"]["bins"],
								"data_length":process["BP_length"],
								"var_name": self.BASDA_Setting["hotmap_variable_name"],
								"X_name": process["plot"]["X_name"],
								"Y_name": process["plot"]["Y_name"],
						}

		for key, folder in self.BASDA_Dir.items():
			if key == "event_general_folder" or key=="event_general_folder_string" or key == "out_table_file":
				continue
			Create_Folder(folder,"/")
		return
		
	def Dir_Print(self):
		print("	The BASDA Dir is : ")
		print("		control_folder         : ", self.BASDA_Dir["control_folder"])
		print("		parallel_output_folder : ", self.BASDA_Dir["parallel_output_folder"])
		print("		out_table_file         : ", self.BASDA_Dir["out_table_file"])
		print("		param_out_file         : ", self.BASDA_Dir["param_out_file"])
		print("		hotmap_variable_name   : ", self.BASDA_Setting["hotmap_variable_name"])
		print("		hotmap_dat_file        : ", self.BASDA_Dir["hotmap_dat_file"])
		print("		hotmap_C_name          : ", self.BASDA_Dir["hotmap_C_file"])

	def Print(self):
		print("\n BASDA Param Content is : ")
		self.Dir_Print()
		self.Control_Print()
		print("_"*50)

	def run_subprocess(self, path_file):
		BASDA_bin = self._param_dir["BASDA"] / "bin" /  "BASDA"
		result = subprocess.run([str(BASDA_bin), path_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
		return(result)


	def Run(self): 
		file_general_name = "path_{}.dat"
		file_name_list=Generate_General_NameList(file_general_name,self.BASDA_Control["dir"]["target"],self._process["BP_length"])
		Create_Folder(self.BASDA_Dir["parallel_output_folder"],"/")
		Parallel_Running(self.run_subprocess, file_name_list,str(self.BASDA_Dir["parallel_output_folder"]))


	def Find_BASDA_OutputTable(self, BASDA_out_name,total_file_num):
		All_sig = []
		for file_num in range(total_file_num):
			format_num=str(file_num+1).rjust(2,"0")
			BASDA_file = BASDA_out_name.format(fnum=format_num)
			if not os.path.exists(BASDA_file):
				print("The folder {} does not exist".format(BASDA_file))
			label = {'\\hline': 1}
			word_list, input_line_list = Find_Line(BASDA_file, label)
			print(BASDA_file)
			if len(input_line_list) == 0:
				All_sig.append('0')
			else:
				strings = word_list[(-2)]
				significance = strings.split()[(-1)]
				All_sig.append(significance[:-2])
		return(All_sig)

	# 收集ARCH结果，并画出热力图
	def Results(self):
		print("In BASDA:, the general BASDA results are stored in ", self.BASDA_Dir["out_table_file"])
		self.BASDA_Results["cross"]=self.Find_BASDA_OutputTable(str(self.BASDA_Dir["out_table_file"]),self._process["BP_length"])

		Generate_Hotmap_Data_from_Para_and_Value(self._process["theoretical"], self._process["plot"]["df_para"], self.BASDA_Results["cross"], self.BASDA_Dir["hotmap_dat_file"], self.BASDA_Setting["plot"]["var_name"])
		Generate_Hotmap_Code(self.BASDA_Setting["plot"], self._param_dir["hotmap_template"])






